home *** CD-ROM | disk | FTP | other *** search
/ Game.EXE 2001 January / Game.EXE_01_2001.iso / demos / Blade of Darkness / data1.cab / Program_Executable_Files / Lib / PythonLib / re.py < prev    next >
Encoding:
Python Source  |  2000-11-16  |  9.6 KB  |  295 lines

  1. #!/usr/bin/env python
  2. # -*- mode: python -*-
  3.  
  4. import sys
  5. import string
  6. from pcre import *
  7.  
  8. #
  9. # First, the public part of the interface:
  10. #
  11.  
  12. # pcre.error and re.error should be the same, since exceptions can be
  13. # raised from either module.
  14.  
  15. # compilation flags
  16.  
  17. I = IGNORECASE
  18. L = LOCALE
  19. M = MULTILINE
  20. S = DOTALL 
  21. X = VERBOSE 
  22.  
  23. #
  24. #
  25. #
  26.  
  27. _cache = {}
  28. _MAXCACHE = 20
  29.  
  30. def _cachecompile(pattern, flags=0):
  31.     key = (pattern, flags)
  32.     try:
  33.         return _cache[key]
  34.     except KeyError:
  35.         pass
  36.     value = compile(pattern, flags)
  37.     if len(_cache) >= _MAXCACHE:
  38.         _cache.clear()
  39.     _cache[key] = value
  40.     return value
  41.  
  42. def match(pattern, string, flags=0):
  43.     return _cachecompile(pattern, flags).match(string)
  44.   
  45. def search(pattern, string, flags=0):
  46.     return _cachecompile(pattern, flags).search(string)
  47.   
  48. def sub(pattern, repl, string, count=0):
  49.     if type(pattern) == type(''):
  50.         pattern = _cachecompile(pattern)
  51.     return pattern.sub(repl, string, count)
  52.  
  53. def subn(pattern, repl, string, count=0):
  54.     if type(pattern) == type(''):
  55.         pattern = _cachecompile(pattern)
  56.     return pattern.subn(repl, string, count)
  57.   
  58. def split(pattern, string, maxsplit=0):
  59.     if type(pattern) == type(''):
  60.         pattern = _cachecompile(pattern)
  61.     return pattern.split(string, maxsplit)
  62.  
  63. def escape(pattern):
  64.     "Escape all non-alphanumeric characters in pattern."
  65.     result = []
  66.     alphanum=string.letters+'_'+string.digits
  67.     for char in pattern:
  68.         if char not in alphanum:
  69.             if char=='\000': result.append('\\000')
  70.             else: result.append('\\'+char)
  71.         else: result.append(char)
  72.     return string.join(result, '')
  73.  
  74. def compile(pattern, flags=0):
  75.     "Compile a regular expression pattern, returning a RegexObject."
  76.     groupindex={}
  77.     code=pcre_compile(pattern, flags, groupindex)
  78.     return RegexObject(pattern, flags, code, groupindex)
  79.     
  80.  
  81. #
  82. #   Class definitions
  83. #
  84.  
  85. class RegexObject:
  86.     def __init__(self, pattern, flags, code, groupindex):
  87.         self.code = code 
  88.         self.flags = flags
  89.         self.pattern = pattern
  90.         self.groupindex = groupindex
  91.  
  92.     def search(self, string, pos=0, endpos=None):
  93.         """Scan through string looking for a match to the pattern, returning
  94.         a MatchObject instance, or None if no match was found."""
  95.  
  96.         if endpos is None or endpos>len(string): 
  97.             endpos=len(string)
  98.         if endpos<pos: endpos=pos
  99.         regs = self.code.match(string, pos, endpos, 0)
  100.         if regs is None:
  101.             return None
  102.         self._num_regs=len(regs)
  103.         
  104.         return MatchObject(self,
  105.                            string,
  106.                            pos, endpos,
  107.                            regs)
  108.     
  109.     def match(self, string, pos=0, endpos=None):
  110.         """Try to apply the pattern at the start of the string, returning
  111.         a MatchObject instance, or None if no match was found."""
  112.  
  113.         if endpos is None or endpos>len(string): 
  114.             endpos=len(string)
  115.         if endpos<pos: endpos=pos
  116.         regs = self.code.match(string, pos, endpos, ANCHORED)
  117.         if regs is None:
  118.             return None
  119.         self._num_regs=len(regs)
  120.         return MatchObject(self,
  121.                            string,
  122.                            pos, endpos,
  123.                            regs)
  124.     
  125.     def sub(self, repl, string, count=0):
  126.         """Return the string obtained by replacing the leftmost
  127.         non-overlapping occurrences of the pattern in string by the
  128.         replacement repl""" 
  129.  
  130.         return self.subn(repl, string, count)[0]
  131.     
  132.     def subn(self, repl, source, count=0): 
  133.         """Return a 2-tuple containing (new_string, number).
  134.         new_string is the string obtained by replacing the leftmost
  135.         non-overlapping occurrences of the pattern in the source
  136.         string by the replacement repl.  number is the number of
  137.         substitutions that were made."""
  138.  
  139.         if count < 0:
  140.             raise error, "negative substitution count"
  141.         if count == 0:
  142.             import sys
  143.             count = sys.maxint
  144.         if type(repl) == type(''):
  145.             if '\\' in repl:
  146.                 repl = lambda m, r=repl: pcre_expand(m, r)
  147.             else:
  148.                 repl = lambda m, r=repl: r
  149.         n = 0           # Number of matches
  150.         pos = 0         # Where to start searching
  151.         lastmatch = -1  # End of last match
  152.         results = []    # Substrings making up the result
  153.         end = len(source)
  154.         while n < count and pos <= end:
  155.             m = self.search(source, pos)
  156.             if not m:
  157.                 break
  158.             i, j = m.span(0)
  159.             if i == j == lastmatch:
  160.                 # Empty match adjacent to previous match
  161.                 pos = pos + 1
  162.                 results.append(source[lastmatch:pos])
  163.                 continue
  164.             if pos < i:
  165.                 results.append(source[pos:i])
  166.             results.append(repl(m))
  167.             pos = lastmatch = j
  168.             if i == j:
  169.                 # Last match was empty; don't try here again
  170.                 pos = pos + 1
  171.                 results.append(source[lastmatch:pos])
  172.             n = n + 1
  173.         results.append(source[pos:])
  174.         return (string.join(results, ''), n)
  175.                                                                             
  176.     def split(self, source, maxsplit=0):
  177.         """Split the \var{source} string by the occurrences of the pattern,
  178.         returning a list containing the resulting substrings."""
  179.  
  180.         if maxsplit < 0:
  181.             raise error, "negative split count"
  182.         if maxsplit == 0:
  183.             import sys
  184.             maxsplit = sys.maxint
  185.         n = 0
  186.         pos = 0
  187.         lastmatch = 0
  188.         results = []
  189.         end = len(source)
  190.         while n < maxsplit:
  191.             m = self.search(source, pos)
  192.             if not m:
  193.                 break
  194.             i, j = m.span(0)
  195.             if i == j:
  196.                 # Empty match
  197.                 if pos >= end:
  198.                     break
  199.                 pos = pos+1
  200.                 continue
  201.             results.append(source[lastmatch:i])
  202.             g = m.groups()
  203.             if g:
  204.                 if type(g)==type( "" ): g = [g]
  205.                 results[len(results):] = list(g)
  206.             pos = lastmatch = j
  207.             n = n + 1
  208.         results.append(source[lastmatch:])
  209.         return results
  210.  
  211.     # The following 3 functions were contributed by Mike Fletcher, and
  212.     # allow pickling and unpickling of RegexObject instances.
  213.     def __getinitargs__(self):
  214.         return (None,None,None,None) # any 4 elements, to work around
  215.                                      # problems with the
  216.                                      # pickle/cPickle modules not yet 
  217.                                      # ignoring the __init__ function
  218.     def __getstate__(self):
  219.         return self.pattern, self.flags, self.groupindex
  220.     def __setstate__(self, statetuple):
  221.         self.pattern = statetuple[0]
  222.         self.flags = statetuple[1]
  223.         self.groupindex = statetuple[2]
  224.         self.code = apply(pcre_compile, statetuple)
  225.  
  226. class MatchObject:
  227.     def __init__(self, re, string, pos, endpos, regs):
  228.         self.re = re
  229.         self.string = string
  230.         self.pos = pos 
  231.         self.endpos = endpos
  232.         self.regs = regs
  233.         
  234.     def start(self, g = 0):
  235.         "Return the start of the substring matched by group g"
  236.         if type(g) == type(''):
  237.             try:
  238.                 g = self.re.groupindex[g]
  239.             except (KeyError, TypeError):
  240.                 raise IndexError, ('group "' + g + '" is undefined')
  241.         return self.regs[g][0]
  242.     
  243.     def end(self, g = 0):
  244.         "Return the end of the substring matched by group g"
  245.         if type(g) == type(''):
  246.             try:
  247.                 g = self.re.groupindex[g]
  248.             except (KeyError, TypeError):
  249.                 raise IndexError, ('group "' + g + '" is undefined')
  250.         return self.regs[g][1]
  251.     
  252.     def span(self, g = 0):
  253.         """Return a tuple containing the start,end of the substring 
  254.         matched by group g"""
  255.         if type(g) == type(''):
  256.             try:
  257.                 g = self.re.groupindex[g]
  258.             except (KeyError, TypeError):
  259.                 raise IndexError, ('group "' + g + '" is undefined')
  260.         return self.regs[g]
  261.     
  262.     def groups(self):
  263.         "Return a tuple containing all subgroups of the match object"
  264.         result = []
  265.         for g in range(1, self.re._num_regs):
  266.             if (self.regs[g][0] == -1) or (self.regs[g][1] == -1):
  267.                 result.append(None)
  268.             else:
  269.                 result.append(self.string[self.regs[g][0]:self.regs[g][1]])
  270.         return tuple(result)
  271.  
  272.     def group(self, *groups):
  273.         "Return one or more groups of the match."
  274.         if len(groups) == 0:
  275.             groups = (0,)
  276.         result = []
  277.         for g in groups:
  278.             if type(g) == type(''):
  279.                 try:
  280.                     g = self.re.groupindex[g]
  281.                 except (KeyError, TypeError):
  282.                     raise IndexError, ('group "' + g + '" is undefined')
  283.             if len(self.regs)<=g: raise IndexError, ('group "' + str(g) + '" is undefined')
  284.             elif (self.regs[g][0] == -1) or (self.regs[g][1] == -1):
  285.                 result.append(None)
  286.             else:
  287.                 result.append(self.string[self.regs[g][0]:self.regs[g][1]])
  288.         if len(result) > 1:
  289.             return tuple(result)
  290.         elif len(result) == 1:
  291.             return result[0]
  292.         else:
  293.             return ()
  294.  
  295.